home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
serial
/
dcon0.000
/
dcon0
/
dcon0.96
/
dcon.doc
< prev
next >
Wrap
Text File
|
1996-07-20
|
30KB
|
929 lines
#!/usr/bin/more
/*
* dcon version 0.9 April 1996.
*
* Copyright (C) 1989,1996 Daniel Chouinard
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted, but not the right to
* distribute the modified code so that only one version of the language
* syntax may be agreed upon.
*
* This software is provided "as is" without express or implied warranty.
*
*
* Send your comments suggestions, or bug reports to
* danny@limestone.kosone.com
*
* Check for later versions of this package in case I (the author) changes
* addresses.
*/
dcon.doc : Documentation for dcon
-- Synopsis
dcon is a scripting language interpreter useful for establishing
communications on serial lines. Some uses included automated scripts
to connect to ISP's, tech support clients, BBS'es, etc... dcon has some
features that are rarely found in other utilities of the same type.
-- Features
- Simple, BASIC-like script language.
- Command-line and file sourcing of script.
- Multi-response waitfor.
- waitquiet permits line stabilization.
- In-line text capture.
- Multi-process support: fork, wait, kill, exit.
- Debugging verbose and log output.
- logging to file.
- Flow control: goto, gosub, return, if, else.
- Low-impact on system resources.
- Time commands and functions.
- String manipulations.
- Environment manipulation: env(), putenv.
- External utilities system calls: system, exec.
-- History
Sat Jul 20 08:19:13 EDT 1996
- Ameliorated error reporting.
Fri Jul 19 22:29:37 EDT 1996
- Got a bug report from Glen Thigpen that dcon-0.91 reports "Token too long"
errors. Found that dcon didn't deal with non-terminated last lines
properly.
Mon Apr 29 21:38:04 EDT 1996
- Got a bug report from J. Van Koll reporting that the included
ppp-ex.scr had two lines that were truncated. Modified ppp-ex.scr
I wrote most (90%) of dcon back in 1989 (it shows in the source code)
when I started doing Unix Apps tech support mostly by modem to customer
systems. I was tired of typing all those passwords and funny call-charging
codes everytime I used cu. Also, the company I worked for needed a system
that would log call times and estimated costs. Thus dcon was born.
Fast forward six or seven years (today) and I was using pppd to connect to
my ISP site. I was somewhat happy with 'chat' but found it lacking flow
control and multiple respone checks from "atdt..." I wanted it to do
different things for "no carrier", "no dial tone", and "busy".
Although I thought that chat's author would probably add more features
to it someday, although minicom probably does the work already, I found
dcon.c on one of my old 45M tapes. So, I tried compiling it on my Linux
box and, lo and behold, wonder of wonders, it did.
In the end, I added a few things to it (kill, fork, wait, 1/100 sec. times)
and there you are.
In this package, you will find source code (don't laugh), documentation and
script examples that should enable you to become a dcon script author in
minutes. It's quite easy if you've programmed in any language, especially
(don't laugh) BASIC. It's nowhere near perfect (don't laugh), the getvalue()
function is brain-dead (don't laugh), has only integer and string variables
(don't laugh), in the a-z range (don't laugh), a limitied set of operators,
functions and commands. You can stop laughing now.
For all its shortcomings, dcon is great to connect you to the outside world
quickly, intelligently, and with versatility. Please stop laughing.
The example scripts in this package are:
Filename Description
------------- --------------------------------------------------------------
ppp-ex.scr Script to connect to an Internet service provider using ppp
with the ISP using an Annex terminal server.
tst.scr Script to test dcon's functionnality. All tests do not use
any communication equipment
loopback.scr Script to test with a loopback installed on a COM port.
If you would like to contribute more scripts to be included in this
package, please do so! scripts for ISPs, BBSs, using cu, sz, rz, kermit,
minicom, seyon, or whatever. Just send them thru E-Mail to the author.
Please comment your scripts.
-- Installation
make dcon (cc -O2 -o dcon dcon.c if you're a purist)
mv dcon /usr/local/bin/ (anywhere that's pointed by your PATH)
cp dcon.doc ..... (anywhere you keep your text doc files)
Note: Makefile not needed.
-- Calling syntax
dcon [-v] [-e] [-t x] [-d device] [-s "script..."] [scriptfile]
-v : Turn verbose on. dcon will print the script and an execution trace
on stderr. This can be re-directed with "2>/tmp/output".
-e : Turn communication echo on. This will display incoming characters
as they are received on stderr.
-t x: Set character x as line separator. This is used to indicate line
cuts when the script is specified on the command line (-s...)
-d x: This opens the serial device x prior to executing the script.
Optionnal. This can also be done in the script proper.
-s x: Specify script. If both -s and scriptfile are specified, scriptfile
is concatenated at the end of the command-line specified script.
x: Specify script file. The script file is read entirely in memory
before it's executed. This argument MUST be specified last.
Note that it's "-d /dev/cua1", not "-d/dev/cua1".
-- Simple examples
- Execute script
dcon script.scr
- Execute script with parameter passing
dcon -t ";" -s "let \$n=555-4411; let \$u=username" script.scr
( This attributes 555-4411 to variable $n and "username" to $u before
the script is executed )
- Shell script example
#!/bin/sh
dcon -s '
open com /dev/cua1
set com 38400n81
send "atdt555-4411^m"
waitfor 60 "connect"
print "Connected!"
exec "cu -l /dev/cua1 -s 38400"
'
( While this works fine, it should be noted that the single quote should
not be used throughout the script, unless escaped with a back-slash )
-- Connect to ISP using PPP script
Here's a script I'm using to connect to my ISP. It's using an Annex terminal
server (very popular) so changing it to your needs should be pretty trivial.
This script is also furnished in non-commented form as "ppp-ex.scr"
The procedure reads:
Wait for login prompt, send user's name, wait for password prompt,
send password, wait for annex prompt, send "ppp", start up ppp, end with
ppp-off. Of course, this script does a bit more...
----------------------------Cut here 8< -----------------------------------
# dcon script to dial-in to ISP
# This is a comment. Note that "rem" can also be used.
let $n="555-4411" # Phone number
let $u="danny" # Username
let $p="rubataga" # Password
let $l=/root/.isplog # Log file
open com /dev/cua1 # Open com port.
set com 38400n81 # No parity, one stop
set senddelay 0.10 # In-between character delay.
let $a=$rpipe("uname -n") # Get name of node
if $a="bill" let $n="9,"+$n set com 19200n81 # From office differences
# Note that the bit after "then" in an if statement can be compounded commands
# ie. commands seperated by spaces. If the condition is false, if skips the
# script to the next line. By the way, "then" is optionnal.
# if a=1 then let $b="blah" is also fine.
# Note that while dcon's variables are integers, time values are
# indicated by floating point constants (resolution: 1/100th of a sec.)
# Because they can only be constants, you cannot do
# let a=3
# waitquiet a 1
# ^ will evaluate to zero, not 3.
# I didn't want to use floats as much as possible cuz' that's kinda slow on
# some systems. (1996 note: Remember: This is a really old program(7 years))
let n=0 #Count how many times
:reset
# That's a label so "goto" may get back here.
inc n #Increment count
if n>3 goto error #Can't reset?
print "\nResetting modem...\n" #Don't forget new-lines!
waitquiet 5 0.5 #1/2 second quiet., 5 max.
if % = -1 goto error #-1 is timeout reached.
send "ATZ^m" #Send ATZ
waitfor 5 "ok" #Modem responds with "ok"
if % != 0 goto reset #If not, reset it again.
let n=0
:dial
waitquiet 2 0.5 #Wait for 1/2 sec. quiet
if % = -1 goto error
inc n #Count dial attempts
let $a=$mid($time(),11,8) #Get time as "23:59:59"
print "\r",$a," Dial attempt #",n #Print it on-screen
send "ATX4DT"+$n+"^m" #Send dial string
waitfor 50 "connect","busy","no dial tone","no carrier"
# Wait for modem response, up to 50 seconds. Note that get, waitfor and
# waitquiet store their result code in % (Like %errorlevel% in dos).
# A time-out would be indicated by -1 in %.
# Note that strings (like the next one) can contain \xxx octal,
# \x (b=backspace,t=tab,f=formfeed,n=newline,r=return, and escape ',",\ )
# ^x notation. (^m=Carriage return)
if % = 1 print " Busy" sleep 2 print "\b\b\b\b\b " goto dial
if % = 2 print "\n\nNo dial tone! Check phone line!\n" goto error
if % = -1 send " " sleep 1 goto dial
if % != 0 goto error
get 5 " ^m" $c
# Get response from modem for no more than 5 seconds up to a space or a
# carriage return and put it in string variable c. Pretty cool.
# At this point, the modem just said "CONNECT" (which waitfor swallowed)
# so we want what's after that (usually connect speed and protocols used).
# Ex.: CONNECT 1440/LAPM/V32/V42BIS/RUTABAGA/ARQ/MNP5/...^M
# ^ Catch from that point. Stop here ^
# Note that the delimiter characters are swallowed and ignored if received
# before anything else.
# (In this example, $c="1440/LAPM...", not " 1440/LAPM...")
let n=0
print "\nConnected :",$c,"\n"
sleep 1
:wake
print "Waiting for Login:...\n"
waitfor 3 "ogin:"
if % = 0 goto gotlogin
print "Sending \^m\n"
send "^m"
inc n
if n < 5 goto wake
print "Could not get login.\n"
goto error
:gotlogin
print "Logging-in...\n"
send $u+"^m"
print "Waiting for Password:\n"
waitfor 10 "word:"
if % != 0 print "Could not get password prompt!\n" goto error
print "Sending password...\n"
send $p+"^m"
print "Waiting for annex prompt...\n"
waitfor 10 "nnex:"
if % != 0 goto error
print "Starting ppp...\n"
send "ppp^m"
fork
if % != 0 goto nonforked
# Ha, here's a funny thing. fork spawns a child process. Both parent and
# child processes continue to execute the script except that the child process
# has 0 in % and the parent has the child's process ID in %. This can be
# used to differentiate between the two so that they may do two different
# things. In this example, the child calls pppd and the parent shows a clock.
# Also, the parent monitors the keyboard so that when ENTER is pressed, it
# closes the link (with ppp-off)
exec "/usr/lib/ppp/pppd lock defaultroute modem "+$dev()+" "+$baud()
# Here the child executes pppd. Note that exec replaces the current process
# with a new one. exec never returns.
# Also note the $dev() and $baud string functions. Coolness.
:nonforked
# Here the parent process shows current and connect time while waiting for
# the user to press ENTER and then closes the link and logs the call.
let $b=$time() #$time()-> "Tue Apr 2 20:51:31 EST 1996"
let d=time() #time()-> number of seconds since 01/01/70 00:00:00GMT
print "Type ENTER to close connection\n"
print "Connected since ",$b,"\n"
print "Connect ",$c," as ",$u,"\n"
:tloop
let $t=$hms(time()-d)
# $hms(x) returns a string time representation in the form HH:MM:SS from
# a number of seconds. Here, we used variable d to note the start of the
# connection. So, later, time()-d is the number of seconds elapsed.
# Thus, $hms(time()-d) Gives us "00:00:00", "00:00:01", "00:00:02",...
# A chronometer, if you will.
print "\r",$mid($time(),11,8)," -> ",$t," "
# This is neat. Print a carriage return (no line-feed, so we stay on a single
# line), the time ($mid as $mid(string,start,length) in Basic), and the
# connect time. Note that the first character of a string is $mid($s,0,1), not
# $mid($s,1,1), as in Basic. $mid can do the job of $left() and $right()
# $left() is obvious, $right is $mid($s,len($s)-l,999) (l=characters desired)
sleep 1
testkey
# Testkey can only test for ENTER since the terminal device is in buffered
# mode. Oh well.
if % = 0 goto tloop # No key? Print the clock stuff again!
# User typed enter, close link.
system "/usr/lib/ppp/ppp-off"
open file $l
# open file appends to a file. ( $l here was defined at the beginning of this
# script. Or had you forgotten? )
fprint $b," - ",$time()," -> ",$t,"\n"
# Log beginning, end, and connect time.
# print ->stdout, eprint ->stderr, fprint -> file, lprint ->verbose log.
close file
sleep 1
exit 0
:error
print "\nGot error #",%,"!\n"
exit 1
----------------------------Cut here 8< -----------------------------------
-- Notes on invocation
For the previous example, I have a .fvwmrc line in my Menu pop-up that reads:
Exec "ISP-PPP" /usr/bin/X11/rxvt -ls -geometry 40x4 -e dcon /root/scr/ppp.scr
This starts up a small window into which the script is executed.
While I'm online I see a neat little timer (I pay for my internet access).
When I want to disconnect from the ISP, I just type ENTER in the window and,
click, it disconnects and the window closes.
From a VT, i just type "callisp" which is a shell script that reads:
#!/bin/sh
dcon /root/scr/ppp.scr
Leave it running there, switch to another VT and get back to it later.
Of course, if you plan to use this script or ppp-ex.scr, you'll have to change
$u (your username), $p (your password), $n (your ISP number), where pppd
is called from (if yours is not in /usr/lib/ppp), same for ppp-off, and you
may have to change a few waitfors to reflect your ISP's prompts. Log in to
your ISP manually and write them down, then modify the script. Try it.
If you have problems, try 'set comecho on' to see what your ISP is saying.
If your script terminates with an error, try calling it with the -v switch
so that you may follow its execution step by step.
-- Programming manual
-- Commands
Command : rem Aliases: #, //
Description : Remark. Rest of line is ignored.
Syntax : Note that a space must follow "rem".
Example:
#This is a remark
// So is this
rem And this.
Command : :
Description : Notes an anchor point for goto or gosub
Syntax : Keyword must not contain any special characters
Example:
:loop
print "The time is ",$time(),"\n"
sleep 1
goto loop
Command : open
Description : Opens a file or a communication device
Syntax : open com device, open com (stdin), open file FILE
Example:
open com /dev/cua1
set com 38400n81
open file "/tmp/log"
fprintf "This is a log\n"
close file
Command : close
Description : closes file previously opened with open
Syntax : close file
Example:
See previous.
Command : exec
Description : Replaces current process with new one
Syntax : exec "command -args..."
Example:
#Finished script, call cu.
exec "cu -l "+$dev()+" -s "+$baud()
Command : exit
Description : terminates script execution with exit code
Syntax : exit exit_code
Example:
:error
exit 1
:exit_ok
exit 0
Command : testkey
Description : Tests keyboard for keystroke, returns 1 in % if present.
Syntax : testkey
Notes : Can only test for ENTER key. Future versions of dcon will test
Notes : for more and return keycode in %.
Example:
let n=1
:loop
print n," sheep... ZZZzzz...\n"
sleep n
inc n
testkey
if % = 0 goto loop
Command : fork
Description : forks process into two.
Syntax : fork
Notes : % returns 0 for child process, new process ID for parent or
Notes : -1 for error.
Example:
fork
if % = -1 goto error
if % = 0 goto child
:parent
...
Command : hset
Description : Set the hundreds counter
Syntax : hset value
Notes : This command resets the hundreds of seconds counter to a value
Notes : for htime to start from.
Example:
hset 0
:loop
print "Time in 1/100 of a sec.: ",htime(),"\n"
sleep 0.01
goto loop
Command : kill
Description : sends a signal to a process
Syntax : kill signal processID
Notes : Both signal and processID are integer values. Same as standard
Notes : unix kill except that signal aliases are not accepted.
Notes : 0 is returned in % if the signal could be sent, -1 otherwise.
Notes : Signal 0 can be used to detect process existance.
Example:
fork
let p=%
if p = 0 goto child
sleep 300
kill 15 p
sleep 1
kill 0 p
if % != 0 print "Child terminated\n" goto ok
print "Could not terminate child!\n"
kill 9 p
sleep 1
kill 0 p
if % = 0 print "Could not kill child!\n" goto error
print "Child killed.\n"
:ok
...
Command : wait
Description : wait for a child process to terminate
Syntax : wait
Notes : Process ID of terminated child is returned in %
Example:
fork
let p=%
if p=0 goto child
if p=-1 goto error
print "Waiting for child to finish..."
wait
print "\n"
if %!=p print "HA! wait didn't return the right process number!\n" goto error
print "Child is done.\n"
Command : system
Description : calls a system (unix) command
Syntax : system "command"
Example:
:dir
print "listing of directory ",$cwd(),\n"
system "ls -l |more"
Command : cd
Description : Change directory
Syntax : cd directory
Notes : -1 is returned in % if the change could not be made.
Example:
cd "duh"
if % != 0 print "Could not cd into duh.\n"
Command : input
Description : input string from keyboard into string variable
Syntax : input $a
Notes : input terminates entry only with the ENTER key. Spaces, tabs
Notes : and other funny characters are all stored in the variable.
Example:
print "Enter your full name :"
input $n
Command : get
Description : get string from communication device
Syntax : get timeout "terminators" $string
Notes : timeout is a float constant, terminators is a list of characters
Notes : that, when received, terminate get. Terminators are ignored when
Notes : received first.
Example:
waitfor 60 "connect"
if % != 0 goto error
get 2 " ^m" $s
print "Connection parameters: ",$s,"\n"
Command : print
Description : print a comma-separated list of arguments
Syntax : print var,stringvar,"text",...
Notes : Spaces and newlines are not automatically added.
Example:
let b=26
let $c="text variables"
print "Contstant text ",b," ",$c," time: ",$time(),"\n"
Command : eprint
Description : print a comma-separated list of arguments on stderr
Syntax : eprint var,stringvar,"text",...
Notes : Like print but on the standard error file descriptor. The error
Notes : output can be re-directed with "2>file" on the command line.
Command : fprint
Description : print a comma-separated list of arguments in a file
Syntax : fprint var,stringvar,"text",...
Notes : Like print but appended to a file previously opened by open.
Command : lprint
Description : print a comma-separated list of arguments to the log
Syntax : fprint var,stringvar,"text",...
Notes : Like print but printed like a log entry if verbose is on.
Notes : logging is sent to stderr.
Command : if
Description : tests a condition
Syntax : if test_condition commands...
Notes : Conditionnaly executes commands if test condition is true. Test
Notes : operators are =, != (not equal), <, and > which all apply to
Notes : integers and strings. If test_condition is false, if skips to
Notes : the next line.
Example:
if n>30 print "Oh-ho! too many sheep!\n" goto error
if n=17 print "Hurray! we've got exactly enough sheep for a party!\n" goto party
if n<17 print "Murray will have to get more sheep.\n" goto getmore
if $z<"z" goto ...
Command : else
Description : Alternatively execute commands if last if tested false
Syntax : else commands...
Example:
if l<350 print "Wow! Imagine that.\n"
else print "Rush Limbaugh is indeed a big fat bastard.\n"
Command : goto
Description : Sends execution somewhere else in the script
Syntax : goto label
Example:
:loop
print "I feel like murdering Bill Gates...\n"
goto loop
Command : gosub
Description : calls a subroutine
Syntax : gosub label
Example:
gosub routine
sleep 1
gosub routine
goto end
:routine
print "Time: ",$time()," Which is ",time()" seconds in the information era.\n"
return
Command : return
Description : Returns from subroutine
Syntax : return
Command : waitquiet
Description : Waits until communication line stops receiving for a time
Syntax : waitquiet timeout quiettime
Notes : both timeout and quiettime are floating time constants
Notes : with 1/100th sec. accuracy. Usefull fo "swallowing" incoming
Notes : characters for a while or waiting for an unknown prompt.
Example:
:closecon
send "logoff^m"
waitquiet 10 0.5
send "yes^m"
Command : waitfor
Description : Waits until one of a list of strings is received
Syntax : waitfor timeout "string1","string2","string3"...
Notes : Timeout is a floating time constant. waitquiet returns
Notes : 0 for the first string received, 1 for the second, etc...
Notes : and -1 for a timeout. Case is ignored by default unless
Notes : ignorecase is set to off.
Example:
:dial
send "atdt555-4411^m"
waitfor 60 "no carrier","busy","no dial tone","voice","connect"
if % = -1 goto timedout
if % = 0 goto nocd
if % = 1 goto redial
if % = 2 goto error
if % = 3 goto hohoho
if % = 4 goto connected
Command : set
Description : sets working parameters
Syntax : set parameter value
Notes :
Command Description
----------------------------- -------------------------------------------------
set echo on|off Keyboard echo on-screen
set comecho on|off Received characters echoed on-screen
set senddelay time_constant In-between character delay for 'send'
set ignorecase on|off Case sensitivity for 'waitfor'
set clocal on|off clocal on = ignore modem signals
set umask octal_constant file mode creation defaults. See man umask
set verbose on|off verbose on = debug output enabled (lots)
set com com_params communication parameters. ex.: 19200n81, 300e71
baud |||
Parity--|||
bits--||
Stop bits----|
Example:
set echo off
print "Password :"
input $p
print "\n"
set echo on
set comecho on
set senddelay 0.1
set ignorecase on
set com 38400n81
...
Command : inc
Description : increments the content of an integer variable by 1.
Syntax : inc x
Notes : x is from a to z.
Command : dec
Description : Decrements the content of an integer variable by 1.
Syntax : inc x
Notes : x is from a to z. Note that "let x=x-1" also works.
Command : let
Description : does a variable assignment
Syntax : let var=content
Example:
let a=5
let b=(time()-a)+5
let $c="Daniel "
let $d=$c+" Chouinard"
Command : send
Description : sends a string to the communication line (modem usually)
Syntax : send string
Example:
send "atdt555-1212^m"
send $g+"^m"
send "The time is "+$time()+"^m^j"
Command : sleep
Description : Pauses execution.
Syntax : sleep float_constant
Notes : float_constant is precise down to 1/100th sec, unless more
Notes : than 100 second, in which case the precision falls down to 1 sec.
Example:
sleep 0.06
sleep 3
sleep 86400 /* A whole day */
Command : putenv
Description : sets an environement variable
Syntax : putenv "var=content"
Notes : Environement variables are automatically exported, never returned.
Notes : Children processes inherit the environment
Example:
...
putenv "SCRIPTDIR=/usr/lib/dcon/scripts"
system "dothat" # dothat reads env. var. SCRIPTDIR...
...
-- Integer functions
I-Function : len
Description : returns the length of a string
Syntax : let x=len($s)
Notes : "" is zero.
I-Function : time
Description : returns time in seconds since Jan 1, 00:00:00 1970 GMT
Syntax : let x=time()
Notes : Used to calculate time differences
I-Function : htime
Description : returns hundreds of seconds since start of script
Syntax : let x=htime()
Notes : Set to a specific value with 'hset'
I-Function : pid
Description : Returns process ID number of current process (dcon's)
Syntax : let x=pid()
Notes :
I-Function : ppid
Description : Returns process ID number of parent process
Syntax : let x=ppid()
Notes : can be used by 'fork'ed child to detect parent process
I-Function : baud
Description : Returns current baudrate of communication line
Syntax : let x=baud()
Notes : See also $baud()
I-Function : val
Description : returns value of string
Syntax : let x=val($x)
Notes : String is not an expression; must only contain [0-9] characters
Notes : Future versions of dcon will be able to evaluate expressions.
Notes : (Maybe) (This was written 6 years ago)
-- String functions
S-Function : time
Description : Returns 24 character local time string
Syntax : let $x=$time()
Notes : Time is in this format: Mon Apr 8 14:21:22 1996
012345678901234567890123
1 2
S-Function : rpipe
Description : Returns the first line from a system piped command
Syntax : let $x=$rpipe("/bin/ls |grep myfile")
Notes : Not very useful unless used with head, tail, grep, etc...
S-Function : env
Description : Returns content of an environment variable
Syntax : let $x=$env("HOME")
Notes : Non-existant variables return an empty string.
S-Function : hms
Description : Converts number of seconds into time string
Syntax : let $x=$hms(x)
Notes : Format is "HH:MM:SS". Useful for chronometer displays
Notes : Use with 'time()', do not try to increment a variable every
Notes : second using 'sleep 1'. (See ISP script example)
Notes : Format becomes "HHH:MM:SS" after 99 hours, 59 minutes, 59s...
S-Function : dev
Description : Returns current communication device pathname
Syntax : let $x=$dev()
Notes : defined by '-d' command line argument or 'open com'
S-Function : cwd
Description : Returns current working directory pathname
Syntax : let $x=$cwd()
Notes : defined by 'cd'
S-Function : baud
Description : Returns string representation of current baud rate
Syntax : let $x=$baud()
Notes : Defined by 'set com'
S-Function : mid
Description : Returns midsection of a string
Syntax : let $x=$mid($s,s,l)
Notes : $s=Source string,s=start, l=length
Notes : s must be less than the length of the string, l can be some
Notes : huge number (9999) to return the right side of a string to
Notes : the end. the first character of a string is position 0, not 1.
Notes : $right() can be done with: $mid($s,strlen($s)-l,l)
-- Test operators
Operator Description Example Result
= equal if 1+2=3 yes
!= not equal if 1+2!=3 no
> Greater than if 1+3>3 yes
< Less than if 1+3<3 no
Strings can be compared using the same operators.
"aaa" < "aab", "aaaa" > "aaa", "Test" != "test", "One" = "One", "A" > "a"
Note that 'set ignorecase on' does NOT apply to string comparisons.
-- Expression operators
Operator Description Example Result
+ Addition let a=2+2 4
+ Concatenation let $b="aa"+"bb" "aabb"
- Substraction let e=2-5 -3
* Multiplication let f=11*2 22
/ Division let g=34/11 3
& Bit-Wise AND let h=42&7 2
| Bit-Wise OR let a=42|5 47
^ Bit-Wise XOR let a=42^7 45
Mixed expression examples:
#Returns number of seconds since 00:00:00
let $t=$time() #Take a snapshot.
let a=(val(mid$($t,11,2))*3600)+(val(mid$($t,14,2))*60)+val(mid$($t,17,2))
#Notice the extra sets of parenthesis because dcon's expression evaluator
#is brain-dead.
#For example, 5-2+1 should give you 4, right? Well, according to getvalue(),
#it actually gives 2, because it does it somewhat from right to left.
#So to evaluate 5-2+1 correctly, use (5-2)+1. If you're using simple, two-
#element calculations, don't worry about it. 5-2 will give you 3.
#Concatenation (Calls cu)
exec "cu -l "+$dev()+" -s "+$baud()"
#In a test condition
if a+c > strlen($c) goto toolong
#String comparison
let $t=$mid($time(),11,8)
if $t > "19:59:59" print "Too late for that!\n" goto toolate
if $t < "08:00:00" print "Too early!\n" goto tooearly
if $t = "00:00:00" print "Oh god! It's Twinkee time!\n"
-- Known bugs
The expression parser!
-- Todo
Man page
Test forked processed closing com device contention
Option: locking (uucp? What's the standard?)
Better testkey (Change stdin mode to raw, update input, system, exec & exit)
getcomchar() (Get one byte from com so a dumb term could be written in a
script. Must be done only after testkey)
Use getopt()
Use indexes for goto labels.
Polling sucks. Could this be (major) changed to be interrupt-driven?
(Do people still use non-16550s out there?)